//<<<+++OPENSOURCE
//<<<+++OPENSOURCE_LICENSE
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT||LIC==GOOGLE

/**
 * @addtogroup FXCRT
 * @{
 */

/**
 * @file
 * @brief FXCRT Extension
 */

//<<<+++OPENSOURCE_MUST_BEGIN
#ifndef _FXCRT_EXTENSION_
#define _FXCRT_EXTENSION_

#ifndef _FX_BASIC_H_
	#include "fx_basic.h"
#endif

#ifndef _FXCRT_COORDINATES_
	#include "fx_coordinates.h"
#endif

#ifndef _FX_XML_H_
	#include "fx_xml.h"
#endif

#ifndef _FX_UNICODE_
    #include "fx_ucd.h"
#endif

#ifndef _FX_ARABIC_
    #include "fx_arb.h"
#endif

//<<<+++OPENSOURCE_MUST_END

#ifndef _FXM_OPENSOURCE_
	//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
	#ifndef _FXCRT_DEBUG_
		#include "fx_debug.h"
	#endif
	//<<<+++OPENSOURCE_MUST_END
#endif

//<<<+++OPENSOURCE_MUST_BEGIN
#ifdef __cplusplus
extern "C" {
#endif

	//*****************************************************************************
	//* Basic functions
	//*****************************************************************************
	/**
	 * @name Basic functions
	 */
	/*@{*/

	FX_FLOAT		FXSYS_tan(FX_FLOAT a);
	FX_FLOAT		FXSYS_logb(FX_FLOAT b, FX_FLOAT x);
	FX_FLOAT		FXSYS_strtof(FX_LPCSTR pcsStr, FX_INT32 iLength = -1, FX_INT32 *pUsedLen = NULL);
	FX_FLOAT		FXSYS_wcstof(FX_LPCWSTR pwsStr, FX_INT32 iLength = -1, FX_INT32 *pUsedLen = NULL);

	FX_LPWSTR		FXSYS_wcsncpy(FX_LPWSTR dstStr, FX_LPCWSTR srcStr, size_t count);
	FX_INT32		FXSYS_wcsnicmp(FX_LPCWSTR s1, FX_LPCWSTR s2, size_t count);
	FX_INT32		FXSYS_strnicmp(FX_LPCSTR s1, FX_LPCSTR s2, size_t count);

	inline FX_BOOL	FXSYS_islower(FX_INT32 ch) {return ch >= 'a' && ch <= 'z';}
	inline FX_BOOL	FXSYS_isupper(FX_INT32 ch) {return ch >= 'A' && ch <= 'Z';}
	inline FX_INT32	FXSYS_tolower(FX_INT32 ch) {return ch < 'A' || ch > 'Z' ? ch : (ch + 0x20);}
	inline FX_INT32 FXSYS_toupper(FX_INT32 ch) {return ch < 'a' || ch > 'z' ? ch : (ch - 0x20);}

	/*@}*/

	//*****************************************************************************
	//* Hash code for string
	//*****************************************************************************
	/**
	 * @name Hash code for string
	 */
	/*@{*/

	//Get hash code for a byte string
	FX_DWORD	FX_HashCode_String_GetA(FX_LPCSTR pStr, FX_INT32 iLength, FX_BOOL bIgnoreCase = FALSE);
	//Get hash code for a wide string
	FX_DWORD	FX_HashCode_String_GetW(FX_LPCWSTR pStr, FX_INT32 iLength, FX_BOOL bIgnoreCase = FALSE);

	/*@}*/
#ifdef __cplusplus
}
#endif

//*****************************************************************************
//* Random Generator
//*****************************************************************************
/**
 * @name Random generator
 */
/*@{*/

#ifdef __cplusplus
extern "C" {
#endif

	/**
	 * @brief	Start MT random generator.
	 * @param[in] dwSeed	a seed value to initialize MT generator.
	 * @return	Return a context object for MT random generator.
	 */
	FX_LPVOID	FX_Random_MT_Start(FX_DWORD dwSeed);

	/**
	 * @brief	Generate an integer from MT random generator.
	 * @param[in] pContext	points to a context object created by FX_Random_MT_Start function.
	 * @return	Return an integer value.
	 */
	FX_DWORD	FX_Random_MT_Generate(FX_LPVOID pContext);

	/**
	 * @brief	Close a context object for MT random generator.
	 * @param[in] pContext	points to a context object created by FX_Random_MT_Start function.
	 */
	void		FX_Random_MT_Close(FX_LPVOID pContext);

	/**
	 * @brief	Generate random integers, base random generator, lower performance for simple applications.
	 * @param[out] pBuffer		points to a buffer which stores generated random values.
	 * @param[in] iCount		specifies the number of the random values, pBuffer should have enough space.
	 */
	void		FX_Random_GenerateBase(FX_LPDWORD pBuffer, FX_INT32 iCount);

	/**
	 * @brief	Generate random integers, normal random generator, normal performance for normal applications.
	 * @param[out] pBuffer		points to a buffer which stores generated random values.
	 * @param[in] iCount		specifies the number of the random values, pBuffer should have enough space.
	 */
	void		FX_Random_GenerateMT(FX_LPDWORD pBuffer, FX_INT32 iCount);

	/**
	 * @brief	Generate random integers, stronger random generator, higher performance for advanced applications.
	 * @param[out] pBuffer		points to a buffer which stores generated random values.
	 * @param[in] iCount		specifies the number of the random values, pBuffer should have enough space.
	 */
	void		FX_Random_GenerateCrypto(FX_LPDWORD pBuffer, FX_INT32 iCount);

#ifdef __cplusplus
}
#endif

/*@}*/
//<<<+++OPENSOURCE_MUST_END

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
//*****************************************************************************
//* GUID utilities
//*****************************************************************************
/**
 * @name GUID utilities
 */
/*@{*/

#ifdef __cplusplus
extern "C" {
#endif

	/**
	 * @brief	Structure for GUID and type definitions
	 */
	typedef struct FX_GUID
	{
		FX_DWORD	data1;
		FX_WORD		data2;
		FX_WORD		data3;
		FX_BYTE		data4[8];
	}FX_GUID, * FX_LPGUID;
	typedef FX_GUID const * FX_LPCGUID;

	/**
	 * @brief	Create a GUID, version 4.
	 * @param[out] pGUID	pointer to store the returned GUID value, cannot be NULL. 
	 */
	void	FX_GUID_CreateV4(FX_LPGUID pGUID);

	/**
	 * @brief	Format GUID to a string
	 * @param[in] pGUID			points to a valid GUID value, cannot be NULL.
	 * @param[out] bsStr		stores the formatted string
	 * @param[in] bSeparator	if bSeparator is TRUE, GUID string will include '-' separating characters.
	 */
	void	FX_GUID_ToString(FX_LPCGUID pGUID, CFX_ByteString &bsStr, FX_BOOL bSeparator = TRUE);

#ifdef __cplusplus
}
#endif

/*@}*/

//*****************************************************************************
//* Base64 encoding
//*****************************************************************************
/**
 * @name Base64 encoding algorithm
 */
/*@{*/

/**
 * @brief	Type defination for external Base64 encoder.
 * @param[in] b		a 6bits data to encode. 
 * @return	Return an encoding wide character value.
 */
typedef FX_WCHAR (*FX_LPBase64Encoder)(FX_DWORD b);

/** @brief Base64 encoding class. */
class CFX_Base64Encoder : public CFX_Object
{
public:
	/** @brief Default constructor. */
	CFX_Base64Encoder(FX_WCHAR wEqual = '=');

	/**
	 * @brief	Set external Base64 encoder.
	 * @param[in] pEncoder		callback function address to provide an external encoder.
	 * @remark	Set NULL pointer for pEncoder if need use default Base64 encoder.
	 */
	void		SetEncoder(FX_LPBase64Encoder pEncoder);

	/**
	 * @brief	Encode byte data array into a byte array.
	 * 
	 * @note	This method uses only standard BASE-64 encoding characters,
	 * 			external encoder set by SetEncoder will be omitted.
	 * 
	 * @param[in] pSrc		source byte data array to encode.
	 * @param[in] iSrcLen 	the length of source byte array, in bytes.
	 * @param[out] pDst 	destination pointer of byte character array.
	 * 
	 * @return	Return the length of total data stored in destination buffer, in byte characters.
	 *			If pDst is a NULL pointer, it returns the necessary buffer size in wide characters.
	 */
	FX_INT32	Encode(FX_LPCBYTE pSrc, FX_INT32 iSrcLen, FX_LPSTR pDst);

	/**
	 * @brief	Encode byte data array into a wide character array.
	 * @param[in] pSrc		source byte data array to encode.
	 * @param[in] iSrcLen 	the length of source byte array, in bytes.
	 * @param[out] pDst 	destination pointer of wide character array.
	 * @return	Return the length of total data stored in destination buffer, in wide characters.
	 *			If pDst is a NULL pointer, it returns the necessary buffer size in wide characters.
	 */
	FX_INT32	Encode(FX_LPCBYTE pSrc, FX_INT32 iSrcLen, FX_LPWSTR pDst);

	/**
	 * @brief	Encode byte string into a wide string.
	 * @param[in] src	source byte string to encode.
	 * @param[out] dst 	destination wide string to store encoded data.
	 * @return	Return the length of total data stored in destination, in wide characters.
	 */
	FX_INT32	Encode(const CFX_ByteStringC &src, CFX_WideString &dst);

	/**
	 * @brief	Encode byte string into a UTF-8 byte string.
	 * @param[in] src	source byte string to encode.
	 * @param[out] dst 	destination byte string to store encoded data.
	 * @return	Return the length of total data stored in destination, in bytes.
	 */
	FX_INT32	Encode(const CFX_ByteStringC &src, CFX_ByteString &dst);

protected:
	FX_LPVOID	m_pData;
	FX_WCHAR	m_wEqual;
};

/*@}*/

//*****************************************************************************
//* Base64 decoding
//*****************************************************************************
/**
 * @name Base64 decoding algorithm
 */
/*@{*/

/**
 * @brief	Type defination for external Base64 decoder.
 * @param[in] wch	a wide character to decode. 
 * @return	Return a 6bits decoded byte value.
 */
typedef FX_BYTE (*FX_LPBase64Decoder)(FX_WCHAR wch);

/** @brief Base64 decoding class. */
class CFX_Base64Decoder : public CFX_Object
{
public:
	/** @brief Default constructor. */
	CFX_Base64Decoder(FX_WCHAR wEqual = '=');

	/**
	 * @brief	Set external Base64 decoder.
	 * @param[in] pDecoder		callback function address to provide an external decoder.
	 * @remark	Set NULL pointer for pDecoder if need use default Base64 decoder.
	 */
	void		SetDecoder(FX_LPBase64Decoder pDecoder);

	/**
	 * @brief	Decode byte character array into byte buffer.
	 * 
	 * @note	This method uses only standard BASE-64 encoding characters,
	 * 			external decoder set by SetDecoder will be omitted.
	 * 
	 * @param[in] pSrc		source byte character array to decode, encoded Base64 data.
	 * @param[in] iSrcLen 	the length of source byte character array.
	 * @param[out] pDst 	destination pointer of byte buffer.
	 * 
	 * @return	Return the length of total data stored in destination buffer, in bytes.
	 *			If pDst is a NULL pointer, it returns the necessary buffer size in bytes.
	 */
	FX_INT32	Decode(FX_LPCSTR pSrc, FX_INT32 iSrcLen, FX_LPBYTE pDst);

	/**
	 * @brief	Decode wide character array into byte buffer.
	 * @param[in] pSrc		source wide character array to decode.
	 * @param[in] iSrcLen 	the length of source wide character array, in wide characters.
	 * @param[out] pDst 	destination pointer of byte data array.
	 * @return	Return the length of total data stored in destination buffer, in bytes.
	 *			If pDst is a NULL pointer, it returns the necessary buffer size in bytes.
	 */
	FX_INT32	Decode(FX_LPCWSTR pSrc, FX_INT32 iSrcLen, FX_LPBYTE pDst);

	/**
	 * @brief	Decode wide string into a byte string.
	 * @param[in] src	source wide character string to decode.
	 * @param[out] dst 	destination byte string to store decoded data.
	 * @return	Return the length of total data stored in destination, in bytes.
	 */
	FX_INT32	Decode(const CFX_WideStringC &src, CFX_ByteString &dst);

	/**
	 * @brief	Decode UTF-8 byte string into a byte string.
	 * @param[in] src	source UTF-8 byte string to decode.
	 * @param[out] dst 	destination byte string to store decoded data.
	 * @return	Return the length of total data stored in destination, in bytes.
	 */
	FX_INT32	Decode(const CFX_ByteStringC &src, CFX_ByteString &dst);

protected:
	FX_LPVOID	m_pData;
	FX_WCHAR	m_wEqual;
};

/*@}*/
//<<<+++OPENSOURCE_MUST_END
#endif

//*****************************************************************************
//* Shell sort template (pointer array, unstable sort algorithm)
//*****************************************************************************
template<class baseType>
class CFX_SSortTemplate
{
public:
	void ShellSort(baseType *pArray, FX_INT32 iCount)
	{
		FXSYS_assert(pArray != NULL && iCount > 0);

		FX_INT32 i, j, gap;
		baseType v1, v2;
		gap = iCount >> 1;
		while (gap > 0){
			for (i = gap; i < iCount; i ++){
				j = i - gap;
				v1 = pArray[i];
				while (j > -1 && (v2 = pArray[j]) > v1){
					pArray[j + gap] = v2;
					j -= gap;
				}
				pArray[j + gap] = v1;
			}
			gap >>= 1;
		}
	}
};


//<<<+++OPENSOURCE_MUST_BEGIN
#endif //_FXCRT_EXTENSION_
//<<<+++OPENSOURCE_MUST_END

/** @} */

//<<<+++OPENSOURCE_END
